﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ticTacToe.Domain
{
    
    /*
     * An encapsulation for a TicTacToe gameboard, gameboard is represented as a simple char array 
     * where the numbers represent the array index:
     * 
     *          0   1   2
     *          3   4   5
     *          6   7   8
     *          
     * An unmarked or free "square" has the char value 'E',          
     * 
     */
    public class Gameboard
    {
        private char[] board;
        private int playCount { get; set; }
        private char nextPlayBelogsTo { get; set; }
        private bool gameOver{ get; set;}
        
        //ctor, initializes the board 
        
        public Gameboard()
        {
            this.board = new char[9] { 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'};
            this.playCount = 0;
            this.nextPlayBelogsTo = 'X';
            this.gameOver = false;
        }
        //resets the board
        public void reset()
        {
            this.board = new char[9] { 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E' };
            this.playCount = 0;
            this.nextPlayBelogsTo = 'X';
            this.gameOver = false;
        }



        /**
         * marks a given square on the board with the given sign
         */
        public bool setMark(char mark, int square)
        {
            if (square > 8 || square < 0)
                return false;
            if (this.board[square] == 'E')
            {
                this.board[square] = mark;
                registerMove();
                return true;
            }
            return false;
        }

        public void setBoard(char[] arr) {
            this.board = arr;
        }

        public void setPlayCount(int c)
        {
            this.playCount = c;
        }
        /**
         * returns the mark in a given square
         */
        public char getMark(int square)
        {
            return this.board[square];
        }

        /**
         * returns the array representing the gameboard
         */
        public char[] getBoard()
        {
            return this.board;
        }
        /**
         * returns who the next player is (or his mark)
         */
        public char getNextPlayBelongsTo() {
            return this.nextPlayBelogsTo;
        }

        public int getPlayCount() {
            return this.playCount;
        }
        
        /**
         * returns a given row on the board as a string
         */
        public String getRow(int row)
        {
            string all = this.board.ToString();
            if (row == 1)
                return (this.board[0].ToString() + this.board[1].ToString() + this.board[2].ToString());
            else if (row == 2)
                return (this.board[3].ToString() + this.board[4].ToString() + this.board[5].ToString());
            else if (row == 3)
                return (this.board[6].ToString() + this.board[7].ToString() + this.board[8].ToString());
            else
                return all;
        }
        /**
         * returns a given column on the board as a string
         */
        public String getCol(int col)
        {
            string all = this.board.ToString();
            if (col == 1)
                return (this.board[0].ToString() + this.board[3].ToString() + this.board[6].ToString());
            else if (col == 2)
                return (this.board[1].ToString() + this.board[4].ToString() + this.board[7].ToString());
            else if (col == 3)
                return (this.board[2].ToString() + this.board[5].ToString() + this.board[8].ToString());
            else
                return all;
        }
        /**
         * returns a given diagonal line on the board as a string
         * @param: direction from "left" top and down or "right" top and down
         */
        public String getDiagonal(string direction)
        {
            string all = this.board.ToString();
            if (direction == "left")
                return (this.board[0].ToString() + this.board[4].ToString() + this.board[8].ToString());
            else if (direction == "right")
                return (this.board[2].ToString() + this.board[4].ToString() + this.board[6].ToString());
            else
                return all;
        }
        /**
         * Returns a string indicating if someone has a winning line. A string is returned 
         * indicating which line looking like this: "1;row;XXX" or 3;col;OOO   X and O signs 
         * indicate which player won.  If there is a draw, "draw" is returned.
         */
        public string checkForWinner() {
            //is there a winning row somewhere
            for (int r = 1; r < 4; r++) {
                if (getRow(r) == "XXX" || getRow(r) == "OOO")
                {
                    this.gameOver = true;
                    return r.ToString() + ";row;" + getRow(r);
                }
            }
            //is there a winning col somewhere
            for (int c = 1; c < 4; c++)
            {
                if (getCol(c) == "XXX" || getCol(c) == "OOO")
                {
                    this.gameOver = true;
                    return c.ToString() + ";col;" + getCol(c);
                }
            }
            //is there a winning diagonal line somewhere
            if (getDiagonal("left") == "XXX" || getDiagonal("left") == "OOO")
            {
                this.gameOver = true;
                return "0;dia;" + getDiagonal("left");
            }
            if (getDiagonal("right") == "XXX" || getDiagonal("right") == "OOO")
            {
                this.gameOver = true;
                return "2;dia;" + getDiagonal("right");
            }
            //9 plays, still no winning line
            if (this.playCount == 9)
            {
                this.gameOver = true;
                return "draw";
            }
            return getNextPlayBelongsTo().ToString();           
        }

        /**
         *  checks for the gameboard value is game over
         *  
         */
        public bool isGameOver() {
            return gameOver;
        }

        /*
         * Keeps track of the count and the who should move next
         */
        private void registerMove() {
            this.playCount++;
            if (this.nextPlayBelogsTo == 'X')
                this.nextPlayBelogsTo = 'O';
            else
                this.nextPlayBelogsTo = 'X';
        }

        

    }

}